package com.jrauto.CarAppBackend.filter;

/**
 * @author : huiMing
 * Date : 2025年06月25日 16:21
 * @version V1.0
 */

import com.jrauto.CarAppBackend.service.impl.CustomUserDetailsService;
import com.jrauto.CarAppBackend.utils.JwtUtil;
import jakarta.annotation.Resource;
import jakarta.servlet.FilterChain;
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.web.authentication.WebAuthenticationDetailsSource;
import org.springframework.stereotype.Component;
import org.springframework.web.filter.OncePerRequestFilter;

import java.io.IOException;

/**
 * JWT 认证过滤器，用于解析请求头中的 JWT Token 并设置 Spring Security 认证上下文
 */
@Component
public class JwtAuthenticationFilter extends OncePerRequestFilter {

    @Resource
    private JwtUtil jwtUtil; // 注入 JWT 工具类

    @Resource
    private CustomUserDetailsService customUserDetailsService; // 注入自定义用户详情服务

    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
            throws ServletException, IOException {

//        // ⭐️⭐️⭐️ 关键改动：在最开始判断是否是 OPTIONS 请求 ⭐️⭐️⭐️
        if ("OPTIONS".equalsIgnoreCase(request.getMethod())) {
            // 如果是 OPTIONS 请求，直接放行，不进行 JWT 认证处理
            // 预检请求（preflight request）通常不带认证信息
            filterChain.doFilter(request, response);
            return; // 结束方法执行
        }

        final String authorizationHeader = request.getHeader("Authorization"); // 获取 Authorization 请求头

//        String phone = null;
        String subject = null; // 修改为 subject，因为它可以是手机号或 openid
        String jwt = null;

        // 检查 Authorization 头是否存在且以 "Bearer " 开头
        if (authorizationHeader != null && authorizationHeader.startsWith("Bearer ")) {
            jwt = authorizationHeader.substring(7); // 提取 JWT Token (去除 "Bearer ")
            try {
//                phone = jwtUtil.extractPhone(jwt); // 从 Token 中提取手机号
// ⭐️ 关键改动：使用 extractSubject 方法提取通用主题 ⭐️
                subject = jwtUtil.extractSubject(jwt); // 从 Token 中提取主题 (可能是手机号或 openid)
            } catch (Exception e) {
                // Token 解析失败或过期等异常
                System.err.println("JWT Token 解析失败或无效: " + e.getMessage());
                // 这里可以根据需要返回特定的错误响应
            }
        }

        // 如果成功提取到手机号，并且当前 Spring Security 上下文中没有认证信息
        if ( subject  != null && SecurityContextHolder.getContext().getAuthentication() == null) {
            UserDetails userDetails = this.customUserDetailsService.loadUserByUsername( subject ); // 从数据库加载用户详情

            // 验证 Token 是否有效
            if (jwtUtil.validateToken(jwt, userDetails.getUsername())) {
                // 构建认证令牌
                UsernamePasswordAuthenticationToken usernamePasswordAuthenticationToken =
                        new UsernamePasswordAuthenticationToken(userDetails, null, userDetails.getAuthorities());
                // 设置认证详情 (如请求IP等)
                usernamePasswordAuthenticationToken
                        .setDetails(new WebAuthenticationDetailsSource().buildDetails(request));
                // 将认证令牌设置到 Spring Security 上下文
                SecurityContextHolder.getContext().setAuthentication(usernamePasswordAuthenticationToken);
            }
        }
        // 继续过滤器链
        filterChain.doFilter(request, response);
    }
}
